using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
using Volo.Abp.MailKit;
using Volo.Abp.Timing;
using Matrix.Notification.Application.Logging;
using Matrix.Notification.Domain.Notifications;

namespace Matrix.Notification.Channels
{
    /// <summary>
    /// 邮件通知通道实现
    /// </summary>
    public class EmailNotificationChannel : INotificationChannel, ITransientDependency
    {
        public string ChannelType => "Email";

        private readonly ILogger<EmailNotificationChannel> _logger;
        private readonly IEmailSender _emailSender;
        private readonly IClock _clock;
        private readonly IBackgroundJobManager _backgroundJobManager;
        private readonly EmailNotificationChannelOptions _options;

        public EmailNotificationChannel(
            ILogger<EmailNotificationChannel> logger,
            IEmailSender emailSender,
            IClock clock,
            IBackgroundJobManager backgroundJobManager,
            IOptions<EmailNotificationChannelOptions> options)
        {
            _logger = logger;
            _emailSender = emailSender;
            _clock = clock;
            _backgroundJobManager = backgroundJobManager;
            _options = options.Value;
        }

        public Task<bool> IsAvailableAsync(CancellationToken cancellationToken = default)
        {
            return Task.FromResult(_options.IsEnabled && _emailSender is MailKitEmailSender);
        }

        public async Task<NotificationChannelResult> SendAsync(
            object notification,
            CancellationToken cancellationToken = default)
        {
            var result = new NotificationChannelResult();

            try
            {
                var emailNotification = notification as EmailNotificationMessage;
                if (emailNotification == null)
                {
                    _logger.LogError("通知对象不是邮件类型");
                    return CreateFailureResult("通知对象不是邮件类型");
                }

                using (var scope = _logger.LogNotificationSending(
                    emailNotification.Id,
                    NotificationChannel.Email,
                    emailNotification.To))
                {
                    var sendResult = await SendEmailAsync(emailNotification, cancellationToken);

                    if (sendResult.Success)
                    {
                        result.IsSuccess = true;
                        result.SuccessCount = 1;
                        result.MessageId = sendResult.MessageId;
                        result.SentAt = _clock.Now;

                        _logger.LogNotificationSent(
                            emailNotification.Id,
                            NotificationChannel.Email,
                            sendResult.MessageId,
                            _clock.Now - emailNotification.CreationTime);
                    }
                    else
                    {
                        result.IsSuccess = false;
                        result.FailureCount = 1;
                        result.ErrorMessage = sendResult.ErrorMessage;

                        _logger.LogNotificationSendFailed(
                            emailNotification.Id,
                            NotificationChannel.Email,
                            sendResult.ErrorMessage ?? "Unknown error",
                            0,
                            _clock.Now - emailNotification.CreationTime);
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogNotificationError(
                    ex,
                    "SendEmail",
                    notification is EmailNotificationMessage ? ((EmailNotificationMessage)notification).Id : null);

                return CreateFailureResult(ex.Message);
            }
        }

        public async Task<NotificationChannelResult> SendBatchAsync(
            IReadOnlyCollection<object> notifications,
            CancellationToken cancellationToken = default)
        {
            var result = new NotificationChannelResult();
            var startTime = _clock.Now;
            var emailNotifications = notifications.Cast<EmailNotificationMessage>().ToList();

            try
            {
                _logger.LogInformation("开始批量发送邮件: {Count}封邮件", emailNotifications.Count);

                foreach (var emailNotification in emailNotifications)
                {
                    var sendResult = await SendAsync(emailNotification, cancellationToken);

                    if (sendResult.IsSuccess)
                    {
                        result.SuccessCount++;
                    }
                    else
                    {
                        result.FailureCount++;
                        result.ErrorMessage = sendResult.ErrorMessage;
                    }
                }

                result.IsSuccess = result.FailureCount == 0;
                result.SentAt = _clock.Now;

                var duration = _clock.Now - startTime;
                _logger.LogInformation(
                    "批量邮件发送完成: 总数={Total}, 成功={Success}, 失败={Failed}, 耗时={Duration}ms",
                    emailNotifications.Count,
                    result.SuccessCount,
                    result.FailureCount,
                    duration.TotalMilliseconds);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量邮件发送失败: {Error}", ex.Message);
                return CreateFailureResult(ex.Message);
            }
        }

        private async Task<EmailSendResult> SendEmailAsync(
            EmailNotificationMessage emailNotification,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var email = new MailMessage
                {
                    To = emailNotification.To,
                    Subject = emailNotification.Subject,
                    Body = emailNotification.HtmlBody ?? emailNotification.TextBody,
                    IsBodyHtml = !string.IsNullOrEmpty(emailNotification.HtmlBody)
                };

                // 设置发件人信息
                if (!string.IsNullOrEmpty(_options.DefaultFromEmail))
                {
                    email.From = _options.DefaultFromEmail;
                    email.FromName = _options.DefaultFromName;
                }

                // 设置收件人姓名
                if (!string.IsNullOrEmpty(emailNotification.ToName))
                {
                    email.To = $"{emailNotification.ToName} <{emailNotification.To}>";
                }

                // 添加抄送
                if (emailNotification.Cc?.Any() == true)
                {
                    foreach (var cc in emailNotification.Cc)
                    {
                        email.CC.Add(cc);
                    }
                }

                // 添加密送
                if (emailNotification.Bcc?.Any() == true)
                {
                    foreach (var bcc in emailNotification.Bcc)
                    {
                        email.BCC.Add(bcc);
                    }
                }

                // 添加附件
                if (emailNotification.Attachments?.Any() == true)
                {
                    foreach (var attachment in emailNotification.Attachments)
                    {
                        email.Attachments.Add(new MailKitAttachment
                        {
                            FileName = attachment.FileName,
                            ContentType = attachment.ContentType,
                            Content = attachment.Content,
                            ContentId = attachment.ContentId
                        });
                    }
                }

                // 添加邮件头
                if (emailNotification.Headers?.Any() == true)
                {
                    foreach (var header in emailNotification.Headers)
                    {
                        email.Headers[header.Key] = header.Value;
                    }
                }

                // 发送邮件
                var sendResult = await _emailSender.SendAsync(email, cancellationToken: cancellationToken);

                return new EmailSendResult
                {
                    Success = sendResult.Success,
                    MessageId = sendResult.MessageId,
                    ErrorMessage = sendResult.ErrorMessage
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送邮件时发生异常: {To}, Subject={Subject}",
                    emailNotification.To, emailNotification.Subject);

                return new EmailSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        /// <summary>
        /// 发送延迟邮件（通过后台任务）
        /// </summary>
        public async Task SendDelayedAsync(
            EmailNotificationMessage emailNotification,
            TimeSpan delay,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation(
                    "安排延迟邮件发送: {To}, Subject={Subject}, 延迟={Delay}分钟",
                    emailNotification.To,
                    emailNotification.Subject,
                    delay.TotalMinutes);

                await _backgroundJobManager.EnqueueAsync(
                    new DelayedEmailSendJobArgs
                    {
                        EmailNotification = emailNotification,
                        ScheduledTime = _clock.Now.Add(delay)
                    },
                    BackgroundJobPriority.Low,
                    cancellationToken: cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "安排延迟邮件发送失败: {To}, Subject={Subject}",
                    emailNotification.To, emailNotification.Subject);
                throw;
            }
        }

        private NotificationChannelResult CreateFailureResult(string errorMessage)
        {
            return new NotificationChannelResult
            {
                IsSuccess = false,
                ErrorMessage = errorMessage,
                SuccessCount = 0,
                FailureCount = 1,
                SentAt = _clock.Now
            };
        }
    }

    /// <summary>
    /// 邮件通知消息
    /// </summary>
    public class EmailNotificationMessage
    {
        /// <summary>
        /// 通知ID
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreationTime { get; set; }

        /// <summary>
        /// 收件人邮箱
        /// </summary>
        public string To { get; set; } = string.Empty;

        /// <summary>
        /// 收件人姓名
        /// </summary>
        public string? ToName { get; set; }

        /// <summary>
        /// 抄送列表
        /// </summary>
        public List<string> Cc { get; set; } = new();

        /// <summary>
        /// 密送列表
        /// </summary>
        public List<string> Bcc { get; set; } = new();

        /// <summary>
        /// 邮件主题
        /// </summary>
        public string Subject { get; set; } = string.Empty;

        /// <summary>
        /// HTML正文
        /// </summary>
        public string? HtmlBody { get; set; }

        /// <summary>
        /// 纯文本正文
        /// </summary>
        public string? TextBody { get; set; }

        /// <summary>
        /// 附件列表
        /// </summary>
        public List<EmailAttachment> Attachments { get; set; } = new();

        /// <summary>
        /// 邮件头信息
        /// </summary>
        public Dictionary<string, string> Headers { get; set; } = new();

        /// <summary>
        /// 优先级
        /// </summary>
        public EmailPriority Priority { get; set; } = EmailPriority.Normal;

        /// <summary>
        /// 是否需要回执
        /// </summary>
        public bool RequestReadReceipt { get; set; } = false;

        /// <summary>
        /// 回复邮箱
        /// </summary>
        public string? ReplyTo { get; set; }

        /// <summary>
        /// 回复姓名
        /// </summary>
        public string? ReplyToName { get; set; }
    }

    /// <summary>
    /// 邮件附件
    /// </summary>
    public class EmailAttachment
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; } = string.Empty;

        /// <summary>
        /// 内容类型
        /// </summary>
        public string ContentType { get; set; } = string.Empty;

        /// <summary>
        /// 文件内容
        /// </summary>
        public byte[] Content { get; set; } = Array.Empty<byte>();

        /// <summary>
        /// Content ID (用于HTML中引用图片)
        /// </summary>
        public string? ContentId { get; set; }
    }

    /// <summary>
    /// 邮件发送结果
    /// </summary>
    public class EmailSendResult
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
    }

    /// <summary>
    /// 延迟邮件发送任务参数
    /// </summary>
    public class DelayedEmailSendJobArgs
    {
        public EmailNotificationMessage EmailNotification { get; set; } = null!;
        public DateTime ScheduledTime { get; set; }
    }

    /// <summary>
    /// 延迟邮件发送后台任务
    /// </summary>
    public class DelayedEmailSendJob : AsyncBackgroundJob<DelayedEmailSendJobArgs>
    {
        private readonly EmailNotificationChannel _emailChannel;

        public DelayedEmailSendJob(EmailNotificationChannel emailChannel)
        {
            _emailChannel = emailChannel;
        }

        public override async Task ExecuteAsync(DelayedEmailSendJobArgs args)
        {
            // 检查是否到了发送时间
            if (DateTime.UtcNow < args.ScheduledTime)
            {
                // 还没到时间，重新调度
                var delay = args.ScheduledTime - DateTime.UtcNow;
                await _emailChannel.SendDelayedAsync(args.EmailNotification, delay);
                return;
            }

            // 发送邮件
            await _emailChannel.SendAsync(args.EmailNotification);
        }
    }

    /// <summary>
    /// 邮件通知通道配置选项
    /// </summary>
    public class EmailNotificationChannelOptions
    {
        /// <summary>
        /// 是否启用
        /// </summary>
        public bool IsEnabled { get; set; } = true;

        /// <summary>
        /// 默认发件人邮箱
        /// </summary>
        public string DefaultFromEmail { get; set; } = string.Empty;

        /// <summary>
        /// 默认发件人姓名
        /// </summary>
        public string DefaultFromName { get; set; } = string.Empty;

        /// <summary>
        /// 最大附件大小（字节）
        /// </summary>
        public long MaxAttachmentSize { get; set; } = 25 * 1024 * 1024; // 25MB

        /// <summary>
        /// 单次批量发送最大数量
        /// </summary>
        public int MaxBatchSize { get; set; } = 100;

        /// <summary>
        /// 批量发送间隔（毫秒）
        /// </summary>
        public int BatchSendInterval { get; set; } = 1000;

        /// <summary>
        /// 是否启用邮件模板缓存
        /// </summary>
        public bool EnableTemplateCache { get; set; } = true;

        /// <summary>
        /// 模板缓存过期时间（分钟）
        /// </summary>
        public int TemplateCacheExpiration { get; set; } = 60;
    }
}